home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / ixemlsrc.lha / ixemul / library / ptrace.c < prev    next >
C/C++ Source or Header  |  1995-12-23  |  8KB  |  296 lines

  1. /*-
  2.  * Copyright (c) 1995 Leonard Norrgard.  All rights reserved.
  3.  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
  4.  * Copyright (c) 1982, 1986, 1989, 1993
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  * (c) UNIX System Laboratories, Inc.
  7.  * All or some portions of this file are derived from material licensed
  8.  * to the University of California by American Telephone and Telegraph
  9.  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  10.  * the permission of UNIX System Laboratories, Inc.
  11.  *
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *    This product includes software developed by the University of
  23.  *    California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  *
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  *
  40.  *    from: @(#)sys_process.c    8.1 (Berkeley) 6/10/93
  41.  */
  42.  
  43. /*
  44.  * References:
  45.  *    (1) Bach's "The Design of the UNIX Operating System",
  46.  *    (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
  47.  *    (3) the "4.4BSD Programmer's Reference Manual" published
  48.  *        by USENIX and O'Reilly & Associates.
  49.  * The 4.4BSD PRM does a reasonably good job of documenting what the various
  50.  * ptrace() requests should actually do, and its text is quoted several times
  51.  * in this file.
  52.  */
  53.  
  54. #define KERNEL
  55. #include "ixemul.h"
  56. #include "kprintf.h"
  57.  
  58. #include <signal.h>
  59. #include <string.h>
  60. #include <sys/ptrace.h>
  61. #include <sys/types.h>
  62. #include <sys/wait.h>
  63. #include <exec/execbase.h>
  64.  
  65. #ifdef DEBUG
  66. #define DP(a) kprintf a
  67. #else
  68. #define DP(a)
  69. #endif
  70.  
  71. int
  72. process_read_regs (struct user *p, struct reg *regs)
  73. {
  74.   bcopy (p->u_regs, regs, sizeof (struct reg));
  75.   return 0;
  76. }
  77.  
  78. int
  79. process_write_regs (struct user *p, struct reg *regs)
  80. {
  81.   bcopy (regs, p->u_regs, sizeof (struct reg));
  82.   return 0;
  83. }
  84.  
  85. int
  86. process_sstep (struct user *t, int sstep)
  87. {
  88.   if (sstep)
  89.     t->u_regs->r_sr |= 0x8000;
  90.   else
  91.     t->u_regs->r_sr &= ~0x8000;
  92.   return 0;
  93. }
  94.  
  95. int
  96. process_set_pc (struct user *t, caddr_t addr)
  97. {
  98.   t->u_regs->r_pc = addr;
  99.   return 0;
  100. }
  101.  
  102. int
  103. ptrace (int request, pid_t pid, caddr_t addr, int data)
  104. {
  105.   unsigned long value;
  106.   struct Task *task;
  107.   struct user *t, *p;
  108.   int step;
  109.   int error;
  110.  
  111.   /* Find the user area of this process.  */
  112.   p = FindTask (0)->tc_TrapData;
  113.  
  114. #ifdef DEBUG
  115.   {
  116.     char *req;
  117.  
  118.     switch (request)
  119.       {
  120.       case PT_TRACE_ME: req = "PT_TRACE_ME"; break;
  121.       case PT_READ_I:   req = "PT_READ_I";   break;
  122.       case PT_READ_D:   req = "PT_READ_D";   break;
  123.       case PT_READ_U:   req = "PT_READ_U";   break;
  124.       case PT_WRITE_I:  req = "PT_WRITE_I";  break;
  125.       case PT_WRITE_D:  req = "PT_WRITE_D";  break;
  126.       case PT_WRITE_U:  req = "PT_WRITE_U";  break;
  127.       case PT_CONTINUE: req = "PT_CONTINUE"; break;
  128.       case PT_KILL:     req = "PT_KILL";     break;
  129.       case PT_STEP:     req = "PT_STEP";     break;
  130.       default: req = "*Unknown request*";    break;
  131.       }
  132.  
  133.     DP(("ptrace (%s, pid=%lx, addr=%lx, data=%lx);\n",
  134.     req, pid, addr, data));
  135.   }
  136. #endif
  137.  
  138.   if (request == PT_TRACE_ME)
  139.     task = FindTask (0);
  140.   else
  141.     task = (struct Task *) pid;
  142.   t = (struct user *) task->tc_TrapData;
  143.  
  144.   /* Check that the arguments are valid.  */
  145.   switch (request)
  146.     {
  147.     case PT_TRACE_ME:
  148.       /* Saying that you're being traced is always OK.  */
  149.       break;
  150.  
  151. #if 0
  152.       /* Can't allow this yet...  Must also check that the task is
  153.      an ixemul.library one.  */
  154.     case PT_ATTACH:
  155.       /* You can't attach to a process if:
  156.      (1) it's the process that's doing the attaching or  */
  157.       if (t == FindTask (0)->tc_TrapData)
  158.     return (EINVAL);
  159.  
  160.       /* (2) it's already being traced.  */
  161.       if (t->p_flag & STRC)
  162.     return (EBUSY);
  163.       break;
  164. #endif
  165.  
  166.     case PT_READ_I:
  167.     case PT_READ_D:
  168.     case PT_READ_U:
  169.     case PT_WRITE_I:
  170.     case PT_WRITE_D:
  171.     case PT_WRITE_U:
  172.     case PT_CONTINUE:
  173.     case PT_KILL:
  174. #ifdef PT_DETACH
  175.     case PT_DETACH:
  176. #endif
  177. #ifdef PT_STEP
  178.     case PT_STEP:
  179. #endif
  180. #ifdef PT_GETREGS
  181.     case PT_GETREGS:
  182. #endif
  183. #ifdef PT_SETREGS
  184.     case PT_SETREGS:
  185. #endif
  186. #ifdef PT_GETFPREGS
  187.     case PT_GETFPREGS:
  188. #endif
  189. #ifdef PT_SETFPREGS
  190.     case PT_SETFPREGS:
  191. #endif
  192.  
  193.       /* You can't do what you want to the process if:  */
  194.  
  195.       /* (1) It's not being traced at all,  */
  196.       if (!(t->p_flag & STRC))
  197.     return EPERM;
  198.  
  199.       /* (2) it's not being traced by _you_, or  */
  200.       if (t->p_pptr->pr_Task.tc_TrapData != p)
  201.     return EBUSY;
  202.  
  203.       /* (3) it's not currently stopped.  */
  204.       if (t->p_stat != SSTOP
  205.       || !(t->p_flag & SWTED))
  206.     return EBUSY;
  207.       break;
  208.  
  209.     default:
  210.       /* It was not a valid request. */
  211.       return EINVAL;
  212.     }
  213.  
  214.   /* Now actually do the job.  */
  215.   step = 0;
  216.  
  217.   switch (request)
  218.     {
  219.     case PT_TRACE_ME:
  220.       /* Child declares it's being traced, just set the trace flag.  */
  221.       t->p_flag |= STRC;
  222.       break;
  223.  
  224.     case PT_READ_I:
  225.     case PT_READ_D:
  226.       value = (*(unsigned char *) addr) << 8;
  227.       value |= *(unsigned char *) (addr + 1);
  228.       return value;
  229.  
  230.     case PT_WRITE_I:
  231.     case PT_WRITE_D:
  232.       *(unsigned char *) addr = data & 0xff;
  233.       *(unsigned char *) (addr + 1) = data >> 8 & 0xff;
  234.       if (request == PT_WRITE_I)
  235.     CacheClearE (addr, 2, CACRF_ClearI);
  236.       else
  237.     CacheClearE (addr, 2, CACRF_ClearD);
  238.       return 0;
  239.  
  240.       /* case PT_READ_U: fixme */
  241.       /* case PT_WRITE_U: fixme */
  242.  
  243.     case PT_STEP:
  244.       /* From the 4.4BSD PRM:
  245.      "Execution continues as in request PT_CONTINUE; however
  246.      as soon as possible after execution of at least one
  247.      instruction, execution stops again. [ ... ]"  */
  248.       step = 1;
  249.       /* fallthrough */
  250.  
  251.     case PT_CONTINUE:
  252.       /* From the 4.4BSD PRM:
  253.      "The data argument is taken as a signal number and the
  254.      child's execution continues at location addr as if it
  255.      incurred that signal.  Normally the signal number will
  256.      be either 0 to indicate that the signal that caused the
  257.      stop should be ignored, or that value fetched out of
  258.      the process's image indicating which signal caused
  259.      the stop.  If addr is (int *)1 then execution continues
  260.      from where it stopped." */
  261.       /* step = 0 done above. */
  262.  
  263.       /* Check that data is a valid signal number or zero.  */
  264.       if (data < 0 || data >= NSIG)
  265.     return EINVAL;
  266.  
  267.       /* Arrange for a single-step, if that's requested and possible.  */
  268.       if ((error = process_sstep (t, step)))
  269.     return error;
  270.  
  271.       /* If the address parameter is not (int *)1, set the pc.  */
  272.       if ((int *)addr != (int *)1)
  273.     if ((error = process_set_pc (t, addr)))
  274.       return error;
  275.  
  276.       /* Finally, deliver the requested signal (or none).  */
  277.     sendsig:
  278.       t->p_xstat = data;
  279.       setrun (task);
  280.       return 0;
  281.  
  282.     case PT_KILL:
  283.       /* Just send the process a KILL signal.  */
  284.       data = SIGKILL;
  285.       goto sendsig;
  286.  
  287.       /* More to come... fixme.  */
  288.  
  289.     default:
  290.       /* Unknown request.  */
  291.       errno = EIO;
  292.       return -1;
  293.     }
  294.   return 0;    /* correct return value? */
  295. }
  296.